package com.zt.questionnaire.service.excel;

import com.zt.questionnaire.common.bean.excel.ReadExcel;
import com.zt.questionnaire.common.bean.question.AnswerBean;
import com.zt.questionnaire.common.bean.question.QuestionBean;
import com.zt.questionnaire.common.config.redis.CacheOperator;
import com.zt.questionnaire.common.service.HReadExcelFather;
import com.zt.questionnaire.common.utils.ObjectUtils;
import com.zt.questionnaire.model.excel.questionnaire.QuestionnaireOptionExcel;
import com.zt.questionnaire.model.excel.questionnaire.QuestionnaireQuestionExcel;
import com.zt.questionnaire.model.excel.questionnaire.QuestionnaireTypeExcel;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.InputStream;
import java.nio.file.Files;
import java.util.*;

/**
 * 本表要放在illness表后面加载，因为这里加载时要获取体质信息
 *
 * @author funnywus
 */
@Slf4j
@Service
public class HExcelQuestionnaireService {


    @Autowired
    private CacheOperator redis;

    /**
     * 问卷类型. 1: ONBORADING问卷
     */
    public static final int QUESTIONNAIRE_TYPE_ONBORADING = 1;
    /**
     * 问卷类型. 2: WEEK1问卷
     */
    public static final int QUESTIONNAIRE_TYPE_WEEK_1 = 2;
    /**
     * 问卷类型. 3: WEEK2问卷
     */
    public static final int QUESTIONNAIRE_TYPE_WEEK_2 = 3;

    /**
     * 所有问卷的类型列表
     */
    public static final List<Integer> QUESTIONNAIRE_TYPE_LIST =
        Arrays.asList(QUESTIONNAIRE_TYPE_ONBORADING, QUESTIONNAIRE_TYPE_WEEK_1, QUESTIONNAIRE_TYPE_WEEK_2);


    /**
     * excel表名
     */
    public static String fileName = "questionnaire.xlsx";

    /**
     * key：问卷id，QuestionnaireQuestionExcel集合
     **/
    private static final String QUESTIONNAIRE_TYPE_MAP_KEY = "questionnaire_type_map";

    /**
     * key：问题id，QuestionnaireQuestionExcel集合
     **/
    private static final String QUESTIONNAIRE_QUESTION_MAP_KEY = "questionnaire_question_map";

    /**
     * key：选项id，value：QuestionnaireOptionExcel对象
     **/
    private static final String QUESTIONNAIRE_OPTION_MAP_KEY = "questionnaire_option_map";

    public static String[] titleNames = null;

    public static String[][] values = null;

    public boolean readExcel() throws Exception {
        File file = new File("file/" + fileName);
        return readExcel(file);
    }

    public boolean readExcel(File file) throws Exception {
        InputStream stream = Files.newInputStream(file.toPath());
        return readExcel(stream, file.getName());
    }

    private boolean readExcel(InputStream stream, String fileName) throws Exception {
        boolean is = true;
        Map<Integer, QuestionnaireTypeExcel> questionTypeMap = new HashMap<>();
        Map<String, QuestionnaireQuestionExcel> questionMap = new HashMap<>();
        Map<String, QuestionnaireOptionExcel> optionMap = new HashMap<>();
        try (XSSFWorkbook wb = new XSSFWorkbook(stream)) {
            int numberOfSheets = wb.getNumberOfSheets();
            for (int i = 0; i < numberOfSheets; i++) {
                Sheet sheet = wb.getSheetAt(i);
                String name = sheet.getSheetName();
                ReadExcel obj = HReadExcelFather.readExcel(sheet, 0, 1);
                titleNames = obj.getTitleNames();
                values = obj.getValues();
                switch (name) {
                    case "type":
                        questionTypeMap = QuestionnaireTypeExcel.load(titleNames, values);
                        break;
                    case "question":
                        questionMap = QuestionnaireQuestionExcel.load(titleNames, values);
                        break;
                    case "option":
                        optionMap = QuestionnaireOptionExcel.load(titleNames, values);
                        break;
                    default:
                        break;
                }
            }

        } finally {
            titleNames = null;
            values = null;
            if (stream != null) {
                stream.close();
            }
        }
        is = checkQuestion(questionTypeMap, questionMap, optionMap);

        redis.remove(QUESTIONNAIRE_TYPE_MAP_KEY);
        redis.setMap(QUESTIONNAIRE_TYPE_MAP_KEY, questionTypeMap);

        redis.remove(QUESTIONNAIRE_QUESTION_MAP_KEY);
        redis.setMap(QUESTIONNAIRE_QUESTION_MAP_KEY, questionMap);

        redis.remove(QUESTIONNAIRE_OPTION_MAP_KEY);
        redis.setMap(QUESTIONNAIRE_OPTION_MAP_KEY, optionMap);

        return is;
    }

    private boolean checkQuestion(Map<Integer, QuestionnaireTypeExcel> questionTypeMap, Map<String, QuestionnaireQuestionExcel> questionMap, Map<String, QuestionnaireOptionExcel> optionMap) {
        boolean is = true;
        for (QuestionnaireTypeExcel questionnaireType : questionTypeMap.values()) {
            List<String> questionIdList = questionnaireType.getQuestionIdList();
            int questionnaireTypeId = questionnaireType.getId();
            if (ObjectUtils.isEmpty(questionIdList)) {
                continue;
            }
            for (String questionId : questionIdList) {
                QuestionnaireQuestionExcel questionnaireQuestion = questionMap.get(questionId);
                if (questionnaireQuestion == null) {
                    is = false;
                    log.info("questionnaire表中type表的question_id_list字段有问题id 找不到 问卷id={}, 问题id={}", questionnaireTypeId, questionId);
                    continue;
                }
                List<String> optionIdList = questionnaireQuestion.getOptionIdList();
                if (ObjectUtils.isEmpty(optionIdList)) {
                    continue;
                }
                for (String optionId : optionIdList) {
                    QuestionnaireOptionExcel questionnaireOption = optionMap.get(optionId);
                    if (questionnaireOption == null) {
                        is = false;
                        log.info("questionnaire表中option表的option_id_list字段有问题id 找不到 问卷id={}, 问题id={}, 选项id={}", questionnaireTypeId, questionId, optionId);
                        continue;
                    }

                    List<String> questionIdList1 = questionnaireOption.getQuestionIdList();
                    if (ObjectUtils.isNotEmpty(questionIdList1)) {
                        for (String questionId2 : questionIdList1) {
                            QuestionnaireQuestionExcel questionnaireQuestion2 = questionMap.get(questionId2);
                            if (questionnaireQuestion2 == null) {
                                is = false;
                                log.info("questionnaire表中option表的question_id_list字段有问题id 找不到 问卷id={}, 问题id={}, 选项id={}, 支线问题={}", questionnaireTypeId, questionId, optionId, questionId2);
                            }
                        }

                    }
                }
            }

        }
        return is;
    }

    /**
     * 获取问题
     *
     * @return
     */
    public Map<String, QuestionnaireQuestionExcel> getQuestionMap() {
        Map<String, QuestionnaireQuestionExcel> value = redis.getMap(QUESTIONNAIRE_QUESTION_MAP_KEY, String.class, QuestionnaireQuestionExcel.class);
        if (!ObjectUtils.isEmpty(value)) {
            return value;
        }
        if (!redis.isExists(QUESTIONNAIRE_QUESTION_MAP_KEY)) {
            try {
                readExcel();
            } catch (Exception e) {
                log.error(e.getMessage(), e);
            }
        }
        return redis.getMap(QUESTIONNAIRE_QUESTION_MAP_KEY, String.class, QuestionnaireQuestionExcel.class);
    }

    /**
     * 获取单个问题
     *
     * @param questionId
     * @return
     */
    public QuestionnaireQuestionExcel getQuestion(String questionId) {
        QuestionnaireQuestionExcel value = redis.getMapValue(QUESTIONNAIRE_QUESTION_MAP_KEY, questionId, QuestionnaireQuestionExcel.class);
        if (!ObjectUtils.isEmpty(value)) {
            return value;
        }
        if (!redis.isExists(QUESTIONNAIRE_QUESTION_MAP_KEY)) {
            try {
                readExcel();
            } catch (Exception e) {
                log.error(e.getMessage(), e);
            }
        }
        return redis.getMapValue(QUESTIONNAIRE_QUESTION_MAP_KEY, questionId, QuestionnaireQuestionExcel.class);
    }

    /**
     * 获取问题
     *
     * @return
     */
    public Map<String, QuestionnaireOptionExcel> getOptionMap() {
        Map<String, QuestionnaireOptionExcel> value = redis.getMap(QUESTIONNAIRE_OPTION_MAP_KEY, String.class, QuestionnaireOptionExcel.class);
        if (!ObjectUtils.isEmpty(value)) {
            return value;
        }
        if (!redis.isExists(QUESTIONNAIRE_OPTION_MAP_KEY)) {
            try {
                readExcel();
            } catch (Exception e) {
                log.error(e.getMessage(), e);
            }
        }
        return redis.getMap(QUESTIONNAIRE_OPTION_MAP_KEY, String.class, QuestionnaireOptionExcel.class);
    }

    /**
     * 获取选项
     *
     * @param id
     * @return
     */
    public QuestionnaireOptionExcel getOption(String id) {
        QuestionnaireOptionExcel obj = redis.getMapValue(QUESTIONNAIRE_OPTION_MAP_KEY, id, QuestionnaireOptionExcel.class);
        if (obj != null) {
            return obj;
        }
        if (!redis.isExists(QUESTIONNAIRE_OPTION_MAP_KEY)) {
            try {
                readExcel();
            } catch (Exception e) {
                log.error(e.getMessage(), e);
            }
        }
        return redis.getMapValue(QUESTIONNAIRE_OPTION_MAP_KEY, id, QuestionnaireOptionExcel.class);
    }

    /**
     * 获取问卷类型
     *
     * @param id
     * @return
     */
    public QuestionnaireTypeExcel getQuestionnaireType(Integer id) {
        QuestionnaireTypeExcel obj = redis.getMapValue(QUESTIONNAIRE_TYPE_MAP_KEY, id, QuestionnaireTypeExcel.class);
        if (obj != null) {
            return obj;
        }
        if (!redis.isExists(QUESTIONNAIRE_TYPE_MAP_KEY)) {
            try {
                readExcel();
            } catch (Exception e) {
                log.error(e.getMessage(), e);
            }
        }
        return redis.getMapValue(QUESTIONNAIRE_TYPE_MAP_KEY, id, QuestionnaireTypeExcel.class);
    }

    /**
     * 获取问卷的问题，包含主线和支线问题
     *
     * @return
     */
    public Map<String, Object> getQuestionAndOption(Integer id) {
        Map<String, Object> map = new HashMap<>(2);
        // 主线问题
        List<QuestionBean> mainQuesList = new ArrayList<>();
        // 支线问题
        Map<String, QuestionBean> branchQuesMap = new HashMap<>();
        QuestionnaireTypeExcel questionnaireType = getQuestionnaireType(id);
        if (questionnaireType == null) {
            return null;
        }
        // 当前问卷对应的问题id列表
        List<String> questionIdList = questionnaireType.getQuestionIdList();
        if (ObjectUtils.isEmpty(questionIdList)) {
            return null;
        }
        Map<String, QuestionnaireQuestionExcel> questionMap = getQuestionMap();
        Map<String, QuestionnaireOptionExcel> optionMap = getOptionMap();
        // 处理主线和支线问题
        handleQuestionMainAndBranch(questionIdList, mainQuesList, branchQuesMap, true, questionMap, optionMap);
        map.put("mainQuesList", mainQuesList);
        map.put("branchQuesMap", branchQuesMap);
        return map;
    }

    /**
     * 递归处理主线问题和支线问题，填充mainQuesList和branchQuesMap
     *
     * @param quesIdList    问题id集合
     * @param mainQuesList  主线问题的集合
     * @param branchQuesMap 支线问题的map
     * @param flag          true: 表示主线问题，false：支线问题
     * @param questionMap
     * @param optionMap
     */
    private void handleQuestionMainAndBranch(List<String> quesIdList, List<QuestionBean> mainQuesList
        , Map<String, QuestionBean> branchQuesMap, boolean flag,
                                             Map<String, QuestionnaireQuestionExcel> questionMap,
                                             Map<String, QuestionnaireOptionExcel> optionMap) {
        for (String questionId : quesIdList) {
            QuestionnaireQuestionExcel question = questionMap.get(questionId);
            if (question == null) {
                continue;
            }
            QuestionBean que = new QuestionBean();
            if (flag) {
                mainQuesList.add(que);
            } else {
                branchQuesMap.put(question.getId(), que);
            }
            que.setId(question.getId());
            que.setTitle(question.getName());
            que.setType(question.getType());
            que.setExample(question.getExample());
            que.setTips(question.getTips());
            que.setLimitType(question.getLimit_type());
            que.setRightContent(question.getRight_content());
            que.setLeftContent(question.getLeft_content());
            que.setIsPrevAnswer(question.getIs_prev_answer());
            que.setAnswer(question.getAnswer());
            que.setSuffix(question.getSuffix());
            que.setOptionStyle(question.getOption_style());
            que.setPlaceholder(question.getPlaceholder());

            List<AnswerBean> optionList = new ArrayList<>();
            que.setItem(optionList);
            List<String> optionIdList = question.getOptionIdList();
            if (optionIdList == null) {
                continue;
            }
            for (String optionId : optionIdList) {
                QuestionnaireOptionExcel option = optionMap.get(optionId);
                if (option == null) {
                    continue;
                }
                AnswerBean ans = new AnswerBean();
                optionList.add(ans);
                String optId = option.getId();
                ans.setId(optId);

                ans.setSubject(option.getContent());
                ans.setExclusion(option.getExclusion());
                List<String> questionIdList = option.getQuestionIdList();
                if (ObjectUtils.isNotEmpty(questionIdList)) {
                    ans.setQuestionIdList(questionIdList);
                    // 继续查找支线问题
                    handleQuestionMainAndBranch(questionIdList, mainQuesList, branchQuesMap, false, questionMap, optionMap);
                }
            }
        }
    }


}
